home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Moscow ML 1.31 / source code / mosml / src / runtime / runtime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-03  |  6.4 KB  |  298 lines  |  [TEXT/R*ch]

  1. /* runtime.c  */
  2.  
  3. #include "runtime.h"
  4.  
  5. #ifdef macintosh
  6.  
  7. /* 23Nov93  e */
  8. /* 16Mar94  e  -- revised to not abuse time manager (!) */
  9. /* 31Aug95  e  -- revised to abuse time manager less (!) */
  10. /* 05Sep95  e  -- added mosml required stuff: gettimeofday, e_getrusage */
  11.  
  12. /* Keeping track of time spent
  13.  - in gc
  14.  - in multifinder
  15.  - overall since startup
  16. */
  17.  
  18. #include <Timer.h>
  19. #include <stdlib.h>
  20.  
  21. #include <time.h>
  22. #include <utime.h>
  23.  
  24. #include "alloc.h"
  25. #include "fail.h"
  26. #include "memory.h"
  27. #include "debugger.h"
  28. #include "mlvalues.h"
  29. #include "freelist.h"
  30. #include "gc.h"
  31. #include "major_gc.h"
  32.  
  33. /* */
  34.  
  35. #define qRunTimes 8 /* must be at least three for: total, gc, mutlifinder */
  36.  
  37. #define aMILLION (1000000L)
  38.  
  39. #if GENERATINGPOWERPC
  40. #pragma options align=mac68k
  41. #endif
  42.  
  43. typedef struct tinfuRec
  44. {
  45.   TMTask TMTask;
  46.   short filler;
  47.   unsigned long  acc_secs;
  48.     signed long acc_usecs;
  49. } tinfuRec, *tinfuPtr;
  50.  
  51. #if GENERATINGPOWERPC
  52. #pragma options align=reset
  53. #endif
  54.  
  55. static tinfuRec gTimeInfo[qRunTimes];
  56.  
  57. #define TIMe(n) (gTimeInfo[n].TMTask)
  58.  
  59. /* 09Jan95 e */
  60.  
  61. static TimerUPP tmt_handlerUPP = NULL;
  62.  
  63. #if powerc
  64. static pascal void tmt_handler(TMTaskPtr a1)
  65. {
  66.   ((tinfuPtr )a1)->acc_secs++;
  67.   PrimeTime((QElemPtr )a1, -aMILLION);
  68. }
  69. #else
  70. #ifndef __MWERKS__
  71. static pascal void tmt_handler(void)
  72. {
  73.   asm
  74.   {
  75.     ADDQ.L #1, tinfuRec.acc_secs(a1)
  76.     MOVE.L A1, A0
  77.     MOVE.L #-aMILLION, D0
  78.     DC.W 0xA05A ; PrimeTime
  79.   }
  80. }
  81. #else
  82. asm static pascal void tmt_handler(void)
  83. {
  84.     ADDQ.L #1, 0x18(A1) // tinfuRec.acc_secs(a1)
  85.     MOVE.L A1, A0
  86.     MOVE.L #-aMILLION, D0
  87.     DC.W 0xA05A // PrimeTime
  88.     RTS
  89. }
  90. #endif
  91. #endif
  92.  
  93. static void cancel_timers(void)
  94. { int i;
  95.   for ( i = 0; i < qRunTimes; i++ )
  96.     // always! 31Aug95 e -- if (TIMe(i).tmAddr != NULL && TIMe(i).qType < 0 )
  97.     { RmvTime((QElemPtr )&TIMe(i));
  98.       TIMe(i).tmAddr = NULL;
  99.     }
  100. }
  101.  
  102. static time_t systime_init;
  103.  
  104. void init_timers(void)
  105. { int i;
  106.   if (tmt_handlerUPP == NULL) tmt_handlerUPP = NewTimerProc(tmt_handler);
  107.   for ( i = 0; i < qRunTimes; i++ )
  108.     if (TIMe(i).tmAddr == NULL)
  109.     { TIMe(i).tmAddr = tmt_handlerUPP;
  110.       // only 0, 31Aug95 e -- InsXTime((QElemPtr )&TIMe(i));
  111.       if ( i == 0 )
  112.       { _atexit(cancel_timers);
  113.         InsXTime((QElemPtr )&TIMe(0));
  114.         systime_init = time(NULL);
  115.         PrimeTime((QElemPtr )&TIMe(0), -aMILLION);
  116.       }
  117.     }
  118. }
  119.  
  120. void beg_runtime(int i)
  121. { tinfuPtr p;
  122.   if ( 0 >= i || i >= qRunTimes ) Debugger(); /* coding error */
  123.   p = &gTimeInfo[i];
  124.   p->TMTask.tmWakeUp = 0;
  125.   p->TMTask.tmReserved = 0;
  126.   InsXTime((QElemPtr )&(p->TMTask));
  127.   PrimeTime((QElemPtr )&(p->TMTask), -aMILLION);
  128. }
  129.  
  130. void acc_runtime(int i)
  131. { tinfuPtr p;
  132.   if ( 0 > i || i >= qRunTimes ) Debugger(); /* coding error */
  133.   p = &gTimeInfo[i];
  134.   RmvTime((QElemPtr )&(p->TMTask));
  135.   p->acc_usecs += aMILLION + p->TMTask.tmCount;
  136.   if (p->acc_usecs >= aMILLION)
  137.   {
  138.     p->acc_secs += 1;
  139.     p->acc_usecs -= aMILLION;
  140.   }
  141.   else if (p->acc_usecs < 0)
  142.   {
  143.     p->acc_secs -= 1;
  144.     p->acc_usecs += aMILLION;
  145.   }
  146. }
  147.  
  148. static double double_zero = (double )0;
  149.  
  150. value get_timer(value x)                          /* ML */
  151. {
  152.   unsigned int i = Long_val(x);
  153.   tinfuPtr p;
  154.  
  155.   if ( 0 > i || i >= qRunTimes) return copy_double(double_zero);
  156.   p = &gTimeInfo[i];
  157.   if (i == 0)
  158.   {
  159.     RmvTime((QElemPtr )&(p->TMTask));
  160.     p->acc_usecs = aMILLION + p->TMTask.tmCount;
  161.     InsXTime((QElemPtr )&(p->TMTask));
  162.     PrimeTime((QElemPtr )&(p->TMTask), 0);
  163.   }
  164.   return copy_double(p->acc_secs + (p->acc_usecs / (double )aMILLION));
  165. }
  166.  
  167. value beg_timer(value x)                          /* ML */
  168. {
  169.   unsigned int i = Long_val(x);
  170.  
  171.   if (i >= qRunTimes || i <= 2) return Val_false;
  172.   beg_runtime(i);
  173.   return Val_true;
  174. }
  175.  
  176. value end_timer(value x)                          /* ML */
  177. {
  178.   unsigned int i = Long_val(x);
  179.  
  180.   if (i >= qRunTimes || i <= 2) return Val_false;
  181.   acc_runtime(i);
  182.   return Val_true;
  183. }
  184.  
  185. value clr_timer(value x)                          /* ML */
  186. {
  187.   unsigned int i = Long_val(x);
  188.   tinfuPtr p;
  189.  
  190.   if (i >= qRunTimes || i <= 2) return Val_false;
  191.   p = &gTimeInfo[i];
  192.   p->acc_secs  = 0;
  193.   p->acc_usecs = 0;
  194.   return Val_true;
  195. }
  196.  
  197. /* runtime stats */
  198.  
  199. value e_getrusage( void )
  200. {
  201.   tinfuPtr p;
  202.   unsigned long rts, sts, gts, uts;
  203.            long rtu, stu, gtu, utu;
  204.   value res = alloc (6, 0);
  205.   /* snapshot run timer */
  206.   p = &gTimeInfo[0];
  207.   RmvTime((QElemPtr )&(p->TMTask));
  208.   rts = p->acc_secs;            // elapsed time
  209.   rtu = p->acc_usecs + aMILLION + p->TMTask.tmCount;
  210.   InsXTime((QElemPtr )&(p->TMTask));
  211.   PrimeTime((QElemPtr )&(p->TMTask), 0);
  212.   /* compute "user" time */
  213.   gts = gTimeInfo[1].acc_secs;  // gc time
  214.   gtu = gTimeInfo[1].acc_usecs;
  215.   sts = gTimeInfo[2].acc_secs;  // multifinder time
  216.   stu = gTimeInfo[2].acc_usecs;
  217.   uts = (rts - sts) - gts;
  218.   utu = (rtu - stu) - gtu;
  219.   while (utu < 0)         { utu += aMILLION; uts -= 1; }
  220.   while (utu >= aMILLION) { utu -= aMILLION; uts += 1; }
  221.   /* pathological case at startup really fries mosml... */
  222.   if (uts > 0x3FFFFFFF)
  223.   {
  224.     uts = 0;
  225.     utu = 1;
  226.   }
  227.   /* fill in SML record */
  228.   Field (res, 0) = Val_long (gts);  // "gc"
  229.   Field (res, 1) = Val_long (gtu);
  230.   Field (res, 2) = Val_long (sts);  // "system"
  231.   Field (res, 3) = Val_long (stu);
  232.   Field (res, 4) = Val_long (uts);  // "user"
  233.   Field (res, 5) = Val_long (utu);
  234.   return res;
  235. }
  236.  
  237. /* end of MacOS specific code */
  238.  
  239. #else
  240.  
  241. /* DOS, Unix */
  242.  
  243. #include <sys/times.h>    
  244. #include <sys/time.h>
  245. #include <sys/resource.h>
  246. #include <unistd.h>   
  247.  
  248. struct mosml_timeval gc_time = { (long) 0, (long) 0 };
  249.  
  250. void beg_gc_time(void)
  251. {
  252. #if defined(hpux) || defined(__svr4__)
  253.   struct tms buffer;
  254.  
  255.   long persec = sysconf(_SC_CLK_TCK);
  256.   times(&buffer);
  257.   gc_time.tv_sec  -= buffer.tms_utime / persec;
  258.   gc_time.tv_usec -= (buffer.tms_utime % persec) * (1000000 / persec);
  259. #else
  260.   struct rusage rusages;
  261.  
  262.   getrusage(RUSAGE_SELF, &rusages);
  263.   gc_time.tv_sec  -= rusages.ru_utime.tv_sec;
  264.   gc_time.tv_usec -= rusages.ru_utime.tv_usec;
  265. #endif
  266.  
  267.   if (gc_time.tv_usec < 0) {
  268.     gc_time.tv_usec += 1000000;
  269.     gc_time.tv_sec  -= 1;
  270.   }
  271. }
  272.  
  273. void end_gc_time(void)
  274. {
  275. #if defined(hpux) || defined(__svr4__)
  276.   struct tms buffer;
  277.  
  278.   long persec = sysconf(_SC_CLK_TCK);
  279.   times(&buffer);
  280.   gc_time.tv_sec  += buffer.tms_utime / persec;
  281.   gc_time.tv_usec += (buffer.tms_utime % persec) * (1000000 / persec);
  282. #else
  283.   struct rusage rusages;
  284.  
  285.   getrusage(RUSAGE_SELF, &rusages);
  286.   gc_time.tv_sec  += rusages.ru_utime.tv_sec;
  287.   gc_time.tv_usec += rusages.ru_utime.tv_usec;
  288. #endif
  289.  
  290.   if (gc_time.tv_usec >= 1000000) {
  291.     gc_time.tv_usec -= 1000000;
  292.     gc_time.tv_sec  += 1;
  293.   }
  294.  
  295. }
  296.  
  297. #endif
  298.